ret
}
-pub fn without_prefix<'a>(a: &'a Path, b: &'a Path) -> Option<&'a Path> {
- let mut a = a.components();
- let mut b = b.components();
+pub fn without_prefix<'a>(long_path: &'a Path, prefix: &'a Path) -> Option<&'a Path> {
+ let mut a = long_path.components();
+ let mut b = prefix.components();
loop {
match b.next() {
Some(y) => match a.next() {
use core::Target;
use ops::is_bad_artifact_name;
use util::errors::CargoResult;
+use util::paths::without_prefix;
use super::{TomlTarget, LibKind, PathValue, TomlManifest, StringOrBool,
TomlLibTarget, TomlBinTarget, TomlBenchTarget, TomlExampleTarget, TomlTestTarget};
}
targets.extend(
- clean_bins(manifest.bin.as_ref(), package_root, package_name, has_lib)?
+ clean_bins(manifest.bin.as_ref(), package_root, package_name, warnings, has_lib)?
);
targets.extend(
fn clean_bins(toml_bins: Option<&Vec<TomlBinTarget>>,
package_root: &Path,
package_name: &str,
+ warnings: &mut Vec<String>,
has_lib: bool) -> CargoResult<Vec<Target>> {
let inferred = inferred_bins(package_root, package_name);
let bins = match toml_bins {
let mut result = Vec::new();
for bin in bins.iter() {
- let path = bin.path.clone().unwrap_or_else(|| {
- PathValue(inferred_bin_path(bin, has_lib, package_root, bins.len()))
- });
- let mut target = Target::bin_target(&bin.name(), package_root.join(&path.0),
+ let path = match target_path(bin, &inferred, "bin", package_root) {
+ Ok(path) => path,
+ Err(e) => {
+ if let Some(legacy_path) = legacy_bin_path(package_root, &bin.name(), has_lib) {
+ {
+ let short_path = without_prefix(&legacy_path, package_root)
+ .unwrap_or(&legacy_path);
+
+ warnings.push(format!(
+ "path `{}` was erroneously implicitly accepted for binary {},\n\
+ please set bin.path in Cargo.toml",
+ short_path.display(), bin.name()
+ ));
+ }
+ legacy_path
+ } else {
+ return Err(e);
+ }
+ }
+ };
+
+ let mut target = Target::bin_target(&bin.name(), path,
bin.required_features.clone());
configure(bin, &mut target);
result.push(target);
}
- Ok(result)
+ return Ok(result);
+
+ fn legacy_bin_path(package_root: &Path, name: &str, has_lib: bool) -> Option<PathBuf> {
+ if !has_lib {
+ let path = package_root.join(format!("src/{}.rs", name));
+ if path.exists() {
+ return Some(path);
+ }
+ }
+ let path = package_root.join("src/main.rs");
+ if path.exists() {
+ return Some(path);
+ }
+
+ let path = package_root.join("src/bin/main.rs");
+ if path.exists() {
+ return Some(path);
+ }
+ return None;
+ }
}
+
fn clean_examples(toml_examples: Option<&Vec<TomlExampleTarget>>,
package_root: &Path)
-> CargoResult<Vec<Target>> {
});
}
-fn inferred_bin_path(bin: &TomlBinTarget,
- has_lib: bool,
- package_root: &Path,
- bin_len: usize) -> PathBuf {
- // here we have a single bin, so it may be located in src/main.rs, src/foo.rs,
- // src/bin/foo.rs, src/bin/foo/main.rs or src/bin/main.rs
- if bin_len == 1 {
- let path = Path::new("src").join("main.rs");
- if package_root.join(&path).exists() {
- return path.to_path_buf();
- }
-
- if !has_lib {
- let path = Path::new("src").join(&format!("{}.rs", bin.name()));
- if package_root.join(&path).exists() {
- return path.to_path_buf();
- }
- }
-
- let path = Path::new("src").join("bin").join(&format!("{}.rs", bin.name()));
- if package_root.join(&path).exists() {
- return path.to_path_buf();
- }
-
- // check for the case where src/bin/foo/main.rs is present
- let path = Path::new("src").join("bin").join(bin.name()).join("main.rs");
- if package_root.join(&path).exists() {
- return path.to_path_buf();
- }
-
- return Path::new("src").join("bin").join("main.rs").to_path_buf();
- }
-
- // bin_len > 1
- let path = Path::new("src").join("bin").join(&format!("{}.rs", bin.name()));
- if package_root.join(&path).exists() {
- return path.to_path_buf();
- }
-
- // we can also have src/bin/foo/main.rs, but the former one is preferred
- let path = Path::new("src").join("bin").join(bin.name()).join("main.rs");
- if package_root.join(&path).exists() {
- return path.to_path_buf();
- }
-
- if !has_lib {
- let path = Path::new("src").join(&format!("{}.rs", bin.name()));
- if package_root.join(&path).exists() {
- return path.to_path_buf();
- }
- }
-
- let path = Path::new("src").join("bin").join("main.rs");
- if package_root.join(&path).exists() {
- return path.to_path_buf();
- }
-
- return Path::new("src").join("main.rs").to_path_buf();
-}
-
fn target_path(target: &TomlTarget,
inferred: &[(String, PathBuf)],
target_kind: &str,
[dependencies.bar]
path = "bar"
-
- [[bin]]
-
- name = "foo"
"#)
- .file("src/foo.rs",
+ .file("src/main.rs",
&main_file(r#""{}", bar::gimme()"#, &["bar"]))
.file("bar/Cargo.toml", r#"
[project]
path = "bar"
"#)
- .file("src/foo.rs", &main_file(r#""i am foo""#, &["bar"]))
+ .file("src/bin/foo.rs", &main_file(r#""i am foo""#, &["bar"]))
.file("bar/Cargo.toml", &basic_bin_manifest("bar"))
.file("bar/src/bar.rs", &main_file(r#""i am bar""#, &[]));
pub fn foo() {}
"#);
assert_that(p.cargo_process("build"), execs().with_status(0).with_stderr_contains("\
-[WARNING] path `src/foo.rs` was erroneously implicitly accepted for library foo,
+[WARNING] path `src[/]foo.rs` was erroneously implicitly accepted for library foo,
please rename the file to `src/lib.rs` or set lib.path in Cargo.toml"));
assert_that(&p.root().join("target/debug/libfoo.rlib"), existing_file());
can't find `hello` example, specify example.path"));
}
+#[test]
+fn non_existing_binary() {
+ let mut p = project("world");
+ p = p.file("Cargo.toml", r#"
+ [package]
+ name = "world"
+ version = "1.0.0"
+ authors = []
+
+ [[bin]]
+ name = "hello"
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/bin/ehlo.rs", "");
+
+ assert_that(p.cargo_process("build").arg("-v"), execs().with_status(101).with_stderr("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ can't find `hello` bin, specify bin.path"));
+}
+
+#[test]
+fn legacy_binary_paths_warinigs() {
+ let mut p = project("world");
+ p = p.file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "1.0.0"
+ authors = []
+
+ [[bin]]
+ name = "bar"
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/main.rs", "fn main() {}");
+
+ assert_that(p.cargo_process("build").arg("-v"), execs().with_status(0).with_stderr_contains("\
+[WARNING] path `src[/]main.rs` was erroneously implicitly accepted for binary bar,
+please set bin.path in Cargo.toml"));
+
+ let mut p = project("world");
+ p = p.file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "1.0.0"
+ authors = []
+
+ [[bin]]
+ name = "bar"
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/bin/main.rs", "fn main() {}");
+
+ assert_that(p.cargo_process("build").arg("-v"), execs().with_status(0).with_stderr_contains("\
+[WARNING] path `src[/]bin[/]main.rs` was erroneously implicitly accepted for binary bar,
+please set bin.path in Cargo.toml"));
+
+ let mut p = project("world");
+ p = p.file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "1.0.0"
+ authors = []
+
+ [[bin]]
+ name = "bar"
+ "#)
+ .file("src/bar.rs", "fn main() {}");
+
+ assert_that(p.cargo_process("build").arg("-v"), execs().with_status(0).with_stderr_contains("\
+[WARNING] path `src[/]bar.rs` was erroneously implicitly accepted for binary bar,
+please set bin.path in Cargo.toml"));
+}
+
#[test]
fn implicit_examples() {
let mut p = project("world");
[[bin]]
name = "foo"
"#)
- .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .file("src/bin/foo.rs", &main_file(r#""i am foo""#, &[]))
.file("d1/Cargo.toml", r#"
[package]
name = "d1"
assert_that(p.cargo_process("build"),
execs().with_status(101)
- .with_stderr_contains(r#"[ERROR] couldn't read "[..]main.rs"[..]"#));
+ .with_stderr_contains("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ can't find `foo` bin, specify bin.path"));
}
[dependencies.dep1]
git = '{}'
-
- [[bin]]
-
- name = "foo"
"#, git_project.url()))
- .file("src/foo.rs", &main_file(r#""{}", dep1::hello()"#, &["dep1"]));
+ .file("src/main.rs", &main_file(r#""{}", dep1::hello()"#, &["dep1"]));
let root = project.root();
let git_root = git_project.root();
git = '{}'
branch = "branchy"
- [[bin]]
-
- name = "foo"
"#, git_project.url()))
- .file("src/foo.rs", &main_file(r#""{}", dep1::hello()"#, &["dep1"]));
+ .file("src/main.rs", &main_file(r#""{}", dep1::hello()"#, &["dep1"]));
let root = project.root();
let git_root = git_project.root();
git = '{}'
tag = "v0.1.0"
-
- [[bin]]
-
- name = "foo"
"#, git_project.url()))
- .file("src/foo.rs", &main_file(r#""{}", dep1::hello()"#, &["dep1"]));
+ .file("src/main.rs", &main_file(r#""{}", dep1::hello()"#, &["dep1"]));
let root = project.root();
let git_root = git_project.root();
version = "0.5.0"
git = '{}'
-
- [[bin]]
-
- name = "foo"
"#, git_project.url()))
- .file("src/foo.rs",
+ .file("src/main.rs",
&main_file(r#""{:?}", bar::bar()"#, &["bar"]));
// First time around we should compile both foo and bar
version = "0.5.0"
path = "bar"
-
- [[bin]]
-
- name = "foo"
"#)
- .file("src/foo.rs",
+ .file("src/main.rs",
&main_file(r#""{}", bar::gimme()"#, &["bar"]))
.file("bar/Cargo.toml", r#"
[project]
version = "0.5.0"
path = "bar"
-
- [[bin]]
-
- name = "foo"
"#)
- .file("src/foo.rs",
+ .file("src/main.rs",
&main_file(r#""{}", bar::gimme()"#, &["bar"]))
.file("bar/Cargo.toml", r#"
[project]
version = "0.5.0"
authors = ["wycats@example.com"]
- [[bin]]
- name = "foo"
[dependencies.bar]
path = "bar"
"#)
- .file("src/foo.rs", r#"
+ .file("src/main.rs", r#"
extern crate bar;
fn main() { bar::bar() }
"#)
p.url())));
sleep_ms(1000);
- p.change_file("src/foo.rs", r#"
+ p.change_file("src/main.rs", r#"
extern crate bar;
fn main() { bar::bar(); }
"#);
version = "0.5.0"
authors = ["wycats@example.com"]
- [[bin]]
- name = "foo"
[dependencies.bar]
path = "bar"
"#)
- .file("src/foo.rs", r#"
+ .file("src/main.rs", r#"
extern crate bar;
fn main() { bar::bar() }
"#)
version = "0.5.0"
authors = ["wycats@example.com"]
- [[bin]]
- name = "foo"
[dependencies.bar]
path = "bar"
[dependencies.baz]
path = "baz"
"#)
- .file("src/foo.rs", r#"
+ .file("src/main.rs", r#"
extern crate bar;
fn main() { bar::bar() }
"#)
version = "0.5.0"
path = "src/bar"
-
- [[bin]]
-
- name = "foo"
"#)
- .file("src/foo.rs",
+ .file("src/main.rs",
&main_file(r#""{}", bar::gimme()"#, &["bar"]))
.file("src/bar/Cargo.toml", r#"
[project]
p.url())));
sleep_ms(1000);
- File::create(&p.root().join("src/foo.rs")).unwrap().write_all(br#"
+ File::create(&p.root().join("src/main.rs")).unwrap().write_all(br#"
fn main() {}
"#).unwrap();
version = "0.5.0"
path = "bar"
-
- [[bin]]
-
- name = "foo"
"#)
- .file("src/foo.rs",
+ .file("src/main.rs",
&main_file(r#""{}", bar::gimme()"#, &["bar"]))
.file("bar/Cargo.toml", r#"
[project]
fn cargo_test_simple() {
let p = project("foo")
.file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", r#"
+ .file("src/main.rs", r#"
fn hello() -> &'static str {
"hello"
}
fn cargo_test_verbose() {
let p = project("foo")
.file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", r#"
+ .file("src/main.rs", r#"
fn main() {}
#[test] fn test_hello() {}
"#);
assert_that(p.cargo_process("test").arg("-v").arg("hello"),
execs().with_status(0).with_stderr(format!("\
[COMPILING] foo v0.5.0 ({url})
-[RUNNING] `rustc [..] src[/]foo.rs [..]`
+[RUNNING] `rustc [..] src[/]main.rs [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
[RUNNING] `[..]target[/]debug[/]deps[/]foo-[..][EXE] hello`", url = p.url()))
.with_stdout_contains("test test_hello ... ok"));
fn cargo_test_failing_test_in_bin() {
let p = project("foo")
.file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", r#"
+ .file("src/main.rs", r#"
fn hello() -> &'static str {
"hello"
}
.with_stdout_contains("[..]`(left == right)`[..]")
.with_stdout_contains("[..]left: `\"hello\"`,[..]")
.with_stdout_contains("[..]right: `\"nope\"`[..]")
- .with_stdout_contains("[..]src[/]foo.rs:12[..]")
+ .with_stdout_contains("[..]src[/]main.rs:12[..]")
.with_stdout_contains("\
failures:
test_hello
fn cargo_test_failing_test_in_test() {
let p = project("foo")
.file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", r#"
+ .file("src/main.rs", r#"
pub fn main() {
println!("hello");
}"#)